package mx.com.zl0.scheduler;

import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;

import mx.com.zl0.scheduler.tasks.SchedulerTask;

public class Scheduler {

	private final SchedulerTask schedulerTask;
	private final Timer timer;

	private class SchedulerTimerTask extends TimerTask {
        public void run() {
            schedulerTask.run();
            reschedule();
        }
    }

    public Scheduler(SchedulerTask schedulerTask) {
    	this(schedulerTask, schedulerTask.isRunAtInit());
    }

    public Scheduler(SchedulerTask schedulerTask, boolean run) {
    	this.schedulerTask = schedulerTask;
    	timer = new Timer();
		if(run) {
			schedule();
		}
    }

    public void cancel() {
    	schedulerTask.cancel();
        timer.cancel();
    }

    public void schedule() {
        final Date time = schedulerTask.getScheduleIterator().next();
        if (time == null) {
            schedulerTask.cancel();
        } else {
            synchronized(schedulerTask.lock) {
                if (schedulerTask.getState() != SchedulerTask.VIRGIN) {
                    throw new IllegalStateException("Task already scheduled or cancelled");
                }
                schedulerTask.setState(SchedulerTask.SCHEDULED);
                schedulerTask.setTimerTask(new SchedulerTimerTask());
                timer.schedule(schedulerTask.getTimerTask(), time);
            }
        }
    }

    public boolean isRunning() {
    	return schedulerTask.isRunning();
    }

    public void reschedule() {
        final Date time = schedulerTask.getScheduleIterator().next();
        if (time == null) {
            schedulerTask.cancel();
        } else {
            synchronized(schedulerTask.lock) {
        		schedulerTask.setState(SchedulerTask.SCHEDULED);
                schedulerTask.setTimerTask(new SchedulerTimerTask());
                timer.schedule(schedulerTask.getTimerTask(), time);
            }
        }
    }

	public SchedulerTask getSchedulerTask() {
		return schedulerTask;
	}
}